package org.metasketch.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.metasketch.javafx.graphics.IJFXGraphicNode;

public class ModelChangeManager {

	Map<CommonIdentified, List<IModelChangeListener>> listeners = new HashMap<CommonIdentified, List<IModelChangeListener>>();

	Map<IModelChangeListener, List<CommonIdentified>> semantics = new HashMap<IModelChangeListener, List<CommonIdentified>>();

	List<IModelChangeListener> simpleListeners = new ArrayList<IModelChangeListener>();

	public List getListeners(CommonIdentified semantic) {

		List list = new ArrayList();

		List<IModelChangeListener> objectListeners = listeners.get(semantic);

		return list;

	}

	// public List getListeners(CommonIdentified semantic, Class type) {
	//
	// List list = new ArrayList();
	//
	// List<IModelChangeListener> objectListeners = listeners.get(semantic);
	// if (objectListeners == null)
	// return list;
	//
	// for (IModelChangeListener listener : objectListeners) {
	// if (type.isAssignableFrom(listener.getClass()))
	// list.add(listener);
	// }
	//
	// return list;
	//
	// }

	public List getListeners(CommonIdentified semantic, Class... types) {

		List list = new ArrayList();

		List<IModelChangeListener> objectListeners = listeners.get(semantic);
		if (objectListeners == null)
			return list;

		for (IModelChangeListener listener : objectListeners) {
			for (int i = 0; i < types.length; i++) {
				Class class1 = types[i];
				if (class1.isAssignableFrom(listener.getClass()))
					list.add(listener);
			}

		}

		return list;

	}

	public void registerListener(CommonIdentified semantic,
			IModelChangeListener listener) {
		List<IModelChangeListener> list = listeners.get(semantic);
		if (list == null) {
			list = new ArrayList<IModelChangeListener>();
			listeners.put(semantic, list);
		}
		
		list.add(listener);
		list.size();
		
		List<CommonIdentified> list2 = semantics.get(listener);
		if (list2 == null) {
			list2 = new ArrayList<CommonIdentified>();
			semantics.put(listener, list2);
		}
		list2.add(semantic);
	}

	public void registerListener(IModelChangeListener listener) {
		simpleListeners.add(listener);
	}

	public void unregisterListener(CommonIdentified semantic,
			IModelChangeListener listener) {

		List<IModelChangeListener> list = listeners.get(semantic);
		if (list != null)
			list.remove(listener);

		List<CommonIdentified> list2 = semantics.get(semantic);
		if (list2 != null)
			list2.remove(semantic);

	}

	public void unregisterListener(IModelChangeListener listener) {
		List<CommonIdentified> list = semantics.get(listener);

		if (list == null)
			return;

		for (CommonIdentified semantic : list) {

			List<IModelChangeListener> list2 = listeners.get(semantic);
			if (list2 != null)
				list2.remove(listener);

		}

		semantics.remove(listener);

		simpleListeners.remove(listener);
	}

	public void unregisterListener(CommonIdentified semantic) {
		List<IModelChangeListener> list = listeners.get(semantic);

		if (list == null)
			return;

		for (IModelChangeListener listener : list) {

			List<CommonIdentified> list2 = semantics.get(listener);
			if (list2 != null)
				list2.remove(semantic);

		}

		listeners.remove(semantic);

	}

	public void addedMainNode(CommonIdentified semantic) {
		List<IModelChangeListener> list = listeners.get(semantic);
		if (list != null) {

			for (IModelChangeListener listener : list) {
				listener.addedMainNode(semantic);
			}
		}
		//
		for (IModelChangeListener listener : simpleListeners) {
			listener.addedMainNode(semantic);
		}

		// alert all other graphics for changes just in case there is any
		// problem whatsoever...
		alertChanges();

	}

	public void removedMainNode(CommonIdentified semantic) {
		List<IModelChangeListener> list = listeners.get(semantic);
		if (list != null) {

			List<IModelChangeListener> toRemove = new ArrayList<IModelChangeListener>();
			toRemove.addAll(list);

			for (IModelChangeListener listener : toRemove) {
				listener.removedMainNode(semantic);
			}
		}

		List<IModelChangeListener> toRemove = new ArrayList<IModelChangeListener>();
		toRemove.addAll(simpleListeners);

		for (IModelChangeListener listener : simpleListeners) {
			listener.removedMainNode(semantic);
		}

		// just in case...remove all listeners
		unregisterListener(semantic);

		// alert all other graphics for changes just in case there is any
		// problem whatsoever...
		alertChanges();

	}

	public void alertChanges(CommonIdentified semantic) {
		List<IModelChangeListener> list = listeners.get(semantic);
		if (list != null) {

			for (IModelChangeListener listener : list) {
				listener.modelChanged(semantic);
			}
		}

		// for (IModelChangeListener listener : simpleListeners) {
		// listener.modelChanged(semantic);
		// }

		// alert all other graphics for changes just in case there is any
		// problem whatsoever...
		alertChanges();

	}

	public void alertChanges() {
		Set<IModelChangeListener> list = semantics.keySet();
		if (list != null) {

			for (IModelChangeListener listener : list) {
				listener.relatedModelChanges();
			}

		}

		for (IModelChangeListener listener : simpleListeners) {
			listener.relatedModelChanges();
		}

	}

}
